--[[
	玩家提现
]]
local filename = "withdrawmoney.lua"

local timetool = require "timetool"
local skynet = require "skynet"
local cluster = require "skynet.cluster"
local json = require "cjson.safe"
local queue = require "skynet.queue"
json.encode_sparse_array(true,1,1)

local filelog =require "filelog"
local redisdao = require "redisdao"
local configdao = require "configdao"
require "pubenum"

--初始化随机数种子
math.randomseed( os.time())
math.random()

local service = nil
local CMD = {
	service = nil
}

local cs = queue()

--
--提现
--
local function withdraw_money(rid, msgbody)
    local value = msgbody.value or 0                    --提现金额，单位分 1分=1金币
    local withdraw_type = msgbody.account_type or 0     --账号类型 1支付宝 2微信 3银行卡
    local accountname = msgbody.accountname or ""       --账号名
    if value <= 0 or withdraw_type <= 0 then
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "无效的参数"}
    end

    --计算手续费
    local service_fee_rate = 0.02    --默认2%手续费,不足1元，算1元
    local status,data = redisdao.query_data(".gmmqredis", "get", "withdraw_service_fee_rate")
    if status and data then
        service_fee_rate = tonumber(data) or 0.02
        if service_fee_rate < 0 or service_fee_rate > 0.1 then
            service_fee_rate = 0.02
        end
    end
    local service_fee = math.ceil((service_fee_rate * value) / 100) * 100

    --获得今日提现次数
    local today_num = 0
    local curtime = timetool.get_time()
    local tm = os.date( "*t", curtime)
    local now_time = curtime - (tm.hour * 3600 + tm.min * 60 + tm.sec)
    local failed_state = tostring(EWithdrawState.EWITHDRAW_STATE_FAILED) or '3'
    local sqlstr = "select count(*) as num from rm_withdraw where rid = " .. (rid or 0) .. " and create_time >= " .. now_time .. " and current_state != " .. failed_state
    local status,result_data = skynet.pcall(cluster.call, "datanode", ".router", "mysqlquery", 1, sqlstr)
    if status and result_data and result_data[1] and result_data[2] and result_data[2][1] then
        today_num = tonumber(result_data[2][1].num) or 0
    else
        return {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "网络繁忙，请稍后重试"}
    end

    --获取实际提现次数
    local today_realnum = 0
    sqlstr = "select count(*) as realnum from rm_withdraw where rid = " .. (rid or 0) .. " and create_time >= " .. now_time
    status,result_data = skynet.pcall(cluster.call, "datanode", ".router", "mysqlquery", 1, sqlstr)
    if status and result_data and result_data[1] and result_data[2] and result_data[2][1] then
        today_realnum = tonumber(result_data[2][1].realnum) or 0
    else
        return {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "网络繁忙，请稍后重试"}
    end
    if today_realnum - today_num > 5 then
        filelog.sys_error("------may withdraw error!------", rid)
    end

    --获得最大提现次数
    local _,withdraw_max_num = redisdao.query_data(".gmmqredis", "hget", "withdraw_max_num", withdraw_type)
    withdraw_max_num = tonumber(withdraw_max_num) or 10  --默认10次
    if today_realnum >= withdraw_max_num then
        return {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "每日最多提现10次"}
    end

    --获得提现最小金额,100的整数倍
    local _,withdraw_min_money = redisdao.query_data(".gmmqredis", "get", "withdraw_min_money")
    withdraw_min_money = tonumber(withdraw_min_money) or 10000  --默认100,最少50
    if withdraw_min_money < 5000 then
        withdraw_min_money = 5000
    end
    if value < withdraw_min_money then
         return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "提现金额至少" .. math.floor(withdraw_min_money / 100) .. "元"}
    end
    
    --提现金额为5的倍数
    --[[
    if (value % 500) ~= 0 then
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "提现金额需为5的倍数" }
    end
    ]]

    --获得单次最大提现金额
    local _,withdraw_max_money = redisdao.query_data(".gmmqredis", "hget", "withdraw_max_money", withdraw_type)
    withdraw_max_money = tonumber(withdraw_max_money) or 100000000  --默认1亿
    if withdraw_max_money < 10000 then
        withdraw_max_money = 10000
    end
    if value > withdraw_max_money then
         return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "提现金额最多" .. math.floor(withdraw_max_money / 100) .. "元"}
    end

    --获得今日最大可提现金额
    local _,today_withdraw_max_money = redisdao.query_data(".gmmqredis", "hget", "today_withdraw_max_money", withdraw_type)
    today_withdraw_max_money = tonumber(today_withdraw_max_money)
    if not today_withdraw_max_money then
        if withdraw_type == EWithdrawType.EWITHDRAW_TYPE_ALIPAY then
            today_withdraw_max_money = 300000   --支付宝默认最大提3000元
        else
            today_withdraw_max_money = 100000000    --其他方式默认100万元
        end
   elseif today_withdraw_max_money < 10000 then
        today_withdraw_max_money = 10000    --最少100元
    end

    --获得今日累积提现金额
    local _, record_data = redisdao.query_data(".gmmqredis", "get", (rid or 0) .. ":withdrawrecord")
    local withdrawrecord = json.decode(record_data or "{}") or { }
    local curday = os.date("%d", curtime)
    if withdrawrecord.record_time then
        local lasttime = tonumber(withdrawrecord.record_time)
        local lastday = os.date("%d", lasttime)
        if lastday ~= curday or (curtime - lasttime) > 86400 then
            withdrawrecord.total_withdraw = {["1001"] = 0}
        end
    end
    withdrawrecord.total_withdraw = withdrawrecord.total_withdraw or {["1001"] = 0}

    --每天第一次提现，不收手续费
    if today_num == 0 then
        service_fee = 0
        withdrawrecord.total_withdraw = {["1001"] = 0}
    end

    local cur_total_withdraw_money = withdrawrecord.total_withdraw[tostring(withdraw_type)] or 0
    cur_total_withdraw_money = tonumber(cur_total_withdraw_money) or 0
    local remain_withdraw_money = today_withdraw_max_money - cur_total_withdraw_money
    if remain_withdraw_money < 0 then remain_withdraw_money = 0 end
    if value > remain_withdraw_money then
        local withdraw_name = ""
        if withdraw_type == EWithdrawType.EWITHDRAW_TYPE_ALIPAY then
            withdraw_name = "支付宝"
        elseif withdraw_type == EWithdrawType.EWITHDRAW_TYPE_BANKCARD then
            withdraw_name = "银行卡"
        elseif withdraw_type == EWithdrawType.EWITHDRAW_TYPE_WEIXIN then
            withdraw_name = "微信"
        end
        if remain_withdraw_money == 0 then
            return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = withdraw_name .. "已达到今日最大提现额度" }
        else
            return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = withdraw_name .. "今日最多还能提现" .. math.floor(remain_withdraw_money / 100) .. "元" }
        end
    end

    --检测钱是否足够
    local basemoney = 500
    local limit_value = value + basemoney
    local cur_money = service.money.diamond or 0
    if cur_money < limit_value then
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "超出最大提现金额"}
    end
    
    --检测打码值是否足够,基础打码值为0才可以提现
    local _,is_close_chipvalue = redisdao.query_data(".gmmqredis", "get", "is_close_chipvalue")
    local base_chipvalue = service.money.base_chipvalue or 0
    if not is_close_chipvalue and (base_chipvalue > 0) then
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "打码值不足，不能提现"}
    end

    --在桌子内不能提现
    if service.gamenode ~= "" then
        return {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "游戏中不能申请提现"}
    end

    --处理提现
    local realname = nil
    local bankname = nil
    local is_ok = true
    if withdraw_type == EWithdrawType.EWITHDRAW_TYPE_ALIPAY then        --提现到支付宝
        bankname = "支付宝"
        realname = service.info.alipay_realname
        if service.info.alipayaccount == "" or service.info.alipayaccount ~= accountname then
            is_ok = false
        end
    elseif withdraw_type == EWithdrawType.EWITHDRAW_TYPE_WEIXIN then    --提现到微信
        bankname = "微信"
        realname = service.info.weixin_realname
        if service.info.weixinaccount == "" or service.info.weixinaccount ~= accountname then
            is_ok = false
        end
    elseif withdraw_type == EWithdrawType.EWITHDRAW_TYPE_BANKCARD then  --提现到银行卡
        realname = service.info.bankcard_realname
        bankname = service.info.bankcard_bankname
        if service.info.bankcardaccount == "" or service.info.bankcardaccount ~= accountname then
            is_ok = false
        end
    else
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "无效的账号类型"}
    end
    if not is_ok then
        return {retcode = EErrCode.ERR_INVALID_PARAMS, retstr = "错误的提现账号"}
    end

    --直接扣除钻石
    local subvalue = -value
    local beginvalue = cur_money
    local realvalue = value - service_fee
    local setargs = service:change_money({diamond = subvalue}, { })
    if setargs then
        --保存提现记录
        local now = timetool.get_time()
        local endvalue = service.money.diamond
        local keyid = skynet.call(".nodeuuid", "lua", "getuuid")
        local tradeid = tostring( os.date("%m%d%H%M%S",now)) .. "_" .. rid .. "_" .. realvalue .. "_" .. value .. "_" .. service_fee .. "_" .. tostring(math.random(100000,999999))
        local fields = {tradeid = tradeid, withdraw_type = withdraw_type, withdraw_value = realvalue, begin_value = beginvalue, end_value = endvalue, service_fee = service_fee, current_state = 0, limit_chipvalue = service.money.limit_chipvalue, phase_chipvalue = service.money.phase_chipvalue}
	    local status,result = skynet.pcall(cluster.call, "datanode", ".router", "insert_rk", rid, "rm_withdraw", keyid, fields)
        if not status or not result or result[1] == 0 or not result[2] then
            --数据回滚
            service:change_money({diamond = -subvalue}, { })
            return {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "系统繁忙，请稍后重试"}
        end

        --记录日志
        local logstr = nil
        local comment = { }
        comment.tradeid = keyid
        comment.table_uuid = "gatenode" .. "_" .. 0 .. "_" .. 0 .. "_" .. now
        --格式：日志类型，rid，level，变化值，初始值，结束值，agent初始值，agent结束值，银行当前值，table_uuid,当前时间，keyid，提现类型，账号，银行名，真实姓名，订单号
        logstr = string.format("%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s,%d,%s,%s,%s,%s", EDiamondChange.WITHDRAW_MONEY, rid, service.info.level, subvalue, 0, 0,
        beginvalue, service.money.diamond, service.money.lock_diamond, comment.table_uuid, now, comment.tradeid, withdraw_type, accountname, bankname, realname, tradeid)
        skynet.send(".diamondlog", "lua", "withdraw_write_file_redis", logstr, rid)

        --提现超1000元，发跑马灯
        if value >= 100000 then
            local popconfig = configdao.get_common_conf("popconfig")
            if popconfig and popconfig[2] then
                local formatname = string.format(ELAMPCOLOR.GREEN, service.info.rolename)
	            local formatmoney = string.format(ELAMPCOLOR.RED, tostring( math.floor(value/100)) )
                local horsestring = string.format(popconfig[2], formatname, formatmoney)
                skynet.send(".router", "lua", "addpopmessage", horsestring)
            end
        end

        --保存今日提现记录
        withdrawrecord.record_time = curtime
        withdrawrecord.total_withdraw[tostring(withdraw_type)] = (withdrawrecord.total_withdraw[tostring(withdraw_type)] or 0) + value
        redisdao.query_data(".gmmqredis", "set", (rid or 0) .. ":withdrawrecord", json.encode(withdrawrecord))
        
        --提现后，重置阶段打码值，限额打码值
        local updatelist = {}
        service.money.limit_chipvalue = 0
        service.money.phase_chipvalue = 0
        updatelist.limit_chipvalue = service.money.limit_chipvalue
        updatelist.phase_chipvalue = service.money.phase_chipvalue
        skynet.pcall(cluster.send, "datanode", ".router", "update_rk", rid, "rs_money", 0, updatelist)
        
    else
        return {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "提现失败，请稍后重试"}
    end

    --等待1s,防止重入
    skynet.sleep(100)

    return {}  
end

-- 处理玩家提现
function CMD.process(rid, msgbody)
	if not service then
		service = CMD.service
	end
    return cs(withdraw_money, rid, msgbody)
end

return CMD
